React.createElement
本质上讲,JSX 只是 React.createElement(component, props, ...children)
的语法糖(JSX 在线Babel编译器)。因此,在用到 JSX 时,即使并没有用到React
,作用域中也必须包含 React 库:import React from 'react'
。例如:
-
写函数组件时,
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
-
配置文件 Object 中包含 JSX:
{ ... render: (data) => <div>{data}</div> ... }
为什么 JSX 中的组件名要以大写字母开头?
小写字母开头: 内置组件,HTML 元素,例如 <div>
,<span>
,会编译成 React.createElement('div')
。
大写字母开头:自定义组件或 JS 文件中导入的组件,例如 <Foo />
,<MyComponents.DatePicker />
,会编译成 React.createElement(Foo)
。
例外:在 JSX 中使用点语法(Dot Notation)表示一个 React 组件 <obj.component />
会编译成 React.createElement(obj.component)
。
解释:JSX 语法依赖babel进行解析。在 @babel/plugin-transform-react-jsx 中,
const visitor = helper({
pre(state) {
const tagName = state.tagName;
const args = state.args;
if (t.react.isCompatTag(tagName)) {
args.push(t.stringLiteral(tagName));
} else {
args.push(state.tagExpr);
}
},
post(state, pass) {
state.callee = pass.get("jsxIdentifier")();
},
throwIfNamespace: THROW_IF_NAMESPACE,
});
function isCompatTag(tagName) {
return !!tagName && /^[a-z]/.test(tagName);
}
即小写字母开头的 tagName 直接转为 string 字符串;
// returns a closure that returns an identifier or memberExpression node
// based on the given id
const createIdentifierParser = (id: string) => () => {
return id
.split(".")
.map(name => t.identifier(name))
.reduce((object, property) => t.memberExpression(object, property));
};
即在 JSX 中使用点语法(Dot Notation)时,不管是大写还是小写,最终都会解析成对象和属性,而不是字符串,也所以虽然 C[p] 和 C.p 一样,但是 JSX 中 <c.p /> 可以解析而 <c[p] /> 不行。
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
// 错误!JSX 类型不能是表达式
return <components[props.storyType] story={props.story} />;
// 正确!JSX 类型可以是一个以大写字母开头的变量.
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}
JSX 是表达式且可以嵌入表达式
JSX 是表达式,编译后就变成常规的 Javascript 对象,所以可以
- 给变量赋值:
const button = <button>{name}</button>
-
当做参数接收
getFieldDecorator('price', { initialValue: { number: 0, currency: 'rmb' }, rules: [{ validator: this.checkPrice }], })(<PriceInput />)
- 作为函数的返回值:
render: () => <Foo />
JSX props 可以用 Javascript 表达式或字符串字面量。props.children(标签中的内容) 是个特殊的 props。
在 JavaScript 中,if 语句和 for 循环不是表达式,因此不能在 JSX 中直接使用。
- JavaScript 逻辑 && 运算符替代 if
- 条件操作符 condition ? true : false 替代 if-else
- map() 函数替代 for 循环
falsy 值渲染
falsy 是在 Boolean 上下文中已认定可转换为‘假’的值。
if (false)
if (null)
if (undefined)
if (0)
if (NaN)
if ('')
if ("")
if (document.all)
false,null,undefined,和 true 是有效的children,但是不会被渲染;
falsy 值例如 0,则会被渲染,例如:
// props.messages 是空数组时,props.messages.length 为 0 会被渲染出来。
<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>
应该改成:
<div>
{props.messages.length > 0 &&
<MessageList messages={props.messages} />
}
</div>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。